#include <mpi.h>

#include <stdio.h>
#include <string.h>  // strlen
#include <stdlib.h>
#include <unistd.h>
  // malloc

#include "parallel_master_slave.h"

int master(int size);
int slave (int size, int rank);
void tnp(void);

int main( int argc, char **argv )
{
	int size, rank; //, i;
	FILE *hostfile;
	char hostname[255];

	hostfile = fopen("hostname.dat", "w");
	gethostname(hostname, sizeof(hostname));
	fprintf(hostfile, "%s", hostname);
	fclose(hostfile);

	/* Inicializiruem biblioteku */
    MPI_Init( &argc, &argv );
    MPI_Comm_size( MPI_COMM_WORLD, &size );
    MPI_Comm_rank( MPI_COMM_WORLD, &rank );

    printf("%d %d %d %d\n",sizeof(int),sizeof(char),sizeof(long),sizeof(short));

    if( rank==0 )
        printf("Total processes count = %d\n", size );

    if( size < 2)
    {
	printf("There must be at least 2 processors\n");
	MPI_Abort( MPI_COMM_WORLD, MPI_ERR_OTHER);
    }
	
    MPI_Barrier( MPI_COMM_WORLD );
    if( rank == 0 )
    	//master(size);
	main_server(1701, size);
    else
    	//slave(size, rank);
	main_slave(rank);

      /* Vse zadac`i zavers`au`t vypolnenie */
    MPI_Finalize();
    return 0;
}
/*
int cut_into_n_parts(
		    int i_min, int j_min, int k_min, 
		    int i_max, int j_max, int k_max,
		    int size,  int rank, 
		    int *imin, int *jmin, int *kmin,
		    int *imax, int *jmax, int *kmax)
{
    int i;
    int di, dj, dk, d1, d2;
    di = i_max - i_min;
    dj = j_max - j_min;
    dk = k_max - k_min;
    if( (di>=dj) && (di>=dk) )
    {
	// cut i
	if (di<size) return 1;
	d1 = di / size;
	d2 = di % size;
	*imin = i_min + d1*rank;
	for(i=0; (i<rank)&&(i<d2); i++)
	{
	    (*imin)++;
	} 	
	*imax = *imin + d1;
	if(rank < d2)
	{
	    (*imax)++;
	}
	*jmin = j_min; *kmin = k_min;
	*jmax = j_max; *kmax = k_max;
	return 0;
    }
    else if ( (dj>=di) && (dj>=dk) )
    {
	// cut j
	if (dj<size) return 1;
	d1 = dj / size;
	d2 = dj % size;
	*jmin = j_min + d1*rank;
	for(i=0; (i<rank)&&(i<d2); i++)
	{
	    (*jmin)++;
	} 	
	*jmax = *jmin + d1;
	if(rank < d2)
	{
	    (*jmax)++;
	}
	*imin = i_min; *kmin = k_min;
	*imax = i_max; *kmax = k_max;
	return 0;
    }
    else
    {
	// cut k
	if (dk<size) return 1;
	d1 = dk / size;
	d2 = dk % size;
	*kmin = k_min + d1*rank;
	for(i=0; (i<rank)&&(i<d2); i++)
	{
	    (*kmin)++;
	} 	
	*kmax = *kmin + d1;
	if(rank < d2)
	{
	    (*kmax)++;
	}
	*jmin = j_min; *imin = i_min;
	*jmax = j_max; *imax = i_max;
	return 0;
    }
}

int master(int size)
{
	int i_min, j_min, k_min;
	int i_max, j_max, k_max;
	int i;
	int buf[8];
	char source[]="iter662.bjn";
	char funcName[]="_CH3O___";
	
	i_min = j_min = k_min = 0;
	i_max = 1;
	j_max = 100;
	k_max = 101;
	
	printf("I am MASTER: size=%d\n", size);
	for(i = 1; i < size; i++)	
	{
	    cut_into_n_parts(
		    i_min, j_min, k_min, 
		    i_max, j_max, k_max,
		    size-1, i-1, 
		    &buf[0], &buf[1], &buf[2],
		    &buf[3], &buf[4], &buf[5]);
	    buf[6]=strlen(source);
	    buf[7]=strlen(funcName);
		//send:
		//	LPCHAR source, LPCHAR funcName
		//	int i0, j0, k0;
		//	int in, jn, kn;
		
		MPI_Send( buf, 8, MPI_INT, i, 0, MPI_COMM_WORLD );
		MPI_Send( source,   buf[6], MPI_CHAR, i, 0, MPI_COMM_WORLD );
		MPI_Send( funcName, buf[7], MPI_CHAR, i, 0, MPI_COMM_WORLD );
	}
	return 0;
}

int slave (int size, int rank)
{
	int buf[8];
	int count;
	char *source, *funcName;
	MPI_Status status;
	MPI_Recv( buf, 8, MPI_INT, 0, 0, MPI_COMM_WORLD, &status );
        MPI_Get_count( &status, MPI_INT, &count );
	if(8!=count) printf("error on %d: recieved %d of 8\n", rank, count);
	source   = (char*) malloc( buf[6] );
	funcName = (char*) malloc( buf[7] );
	MPI_Recv( source,   buf[6], MPI_CHAR, 0, 0, MPI_COMM_WORLD, &status );
	MPI_Recv( funcName, buf[7], MPI_CHAR, 0, 0, MPI_COMM_WORLD, &status );
	printf("I am slave%2d: size=%d ||%d %d %d %d %d %d %d %d %s %s\n", rank, size,
		buf[0], buf[1], buf[2], buf[3], 
		buf[4], buf[5], buf[6], buf[7],
		source, funcName);
	free(source);
	free(funcName);
	return 0;
}
*/
